/****************************************************************************
 *
 *              YASK_test_APM.c -- Tests for YASK on APM board
 *
 *****************************************************************************
 * FileName:        YASK_test_APM.c
 * Processor:       PIC18F
 * Creation date :	2010/09/25
 * Description :	Tests for YASK on APM board
 * Author :			Gilles KREBS
 * License :		Creative Commons 3.0 CC-BY-NC-SA
 *****************************************************************************/
 /*****************************************************************************
 *	NOTES :
 * 
 *****************************************************************************/
 
/*****************************************************************************
 * Machine dependent hardware abstraction layers
 *****************************************************************************/
#include "GENp18.h"
#include "SYSp18.h"
#include "IOSp18.h"
#include "I2Cp18_sw.h"
#include "SPIp18.h"
#include "TTYp18.h"
#include "FSMp18.h"
#include "ADCp18.h"
#include "MPPp18.h"
#include "PPMp18.h"
#include "LT08pic.h"

/*****************************************************************************
 * Portable layers
 *****************************************************************************/
#include "YASKpic.h"

/*****************************************************************************
 * Configuration bits
 *****************************************************************************/
// CONFIG1H : HS clock
#pragma romdata CONFIG1H = 0x300001
const rom unsigned char config1H = 0b000000010;

// CONFIG2L : Brown-out Reset Enabled in hardware @ 2.0V, PWRTEN enabled
#pragma romdata CONFIG2L = 0x300002
const rom unsigned char config2L = 0b00011110;

// CONFIG2H : HW WD disabled, 1:32 prescaler
#pragma romdata CONFIG2H = 0x300003
const rom unsigned char config2H = 0b00010000;	

// CONFIG 3H : PORTB digital on RESET
#pragma romdata CONFIG3H = 0x300005
const rom unsigned char config3H = 0b10000000;	

// CONFIG4L : DEBUG disabled, XINST enabled, LVP disabled, STVREN enabled
#pragma romdata CONFIG4L = 0x300006
const rom unsigned char config4L = 0b11000001;

/*****************************************************************************
 * APM specific definitions
 *****************************************************************************/
// Run LED
#define APM_LED_RUN 			LATAbits.LATA2
#define APM_LED_ON				LATAbits.LATA2 = 1
#define APM_LED_OFF				LATAbits.LATA2 = 0
#define APM_LED_RUN_TRIS 		TRISAbits.TRISA2
#define APM_LED_RUN_TOGGLE 		(APM_LED_RUN ^= 1)

// Push button
#define APM_PB_CNF				PORTAbits.RA1
#define APM_PB_CNF_TRIS 		TRISAbits.TRISA1

// Miscellaneous
#define IN	1
#define OUT	0

// Applicative tasks definition
#define APPmain		app_main

// 
#define LCD_RS	0x80
#define LCD_RW	0x40
#define LCD_E	0x20
#define LCD_BL	0x10
#define LCD_D7	0x08
#define LCD_D6	0x04
#define LCD_D5	0x02
#define LCD_D4	0x01

/*****************************************************************************
 * Prototypes
 *****************************************************************************/
VOID	apm_hal_init( VOID);

// 
VOID 	APPmrx_task(YASK_MSG_T *my_mbx);
VOID	APPled_task( YASK_MSG_T *p); // this task manages the run LED
VOID	APPkbd_serv( YASK_MSG_T *p); // this service posts a mail to the buzzer task on each keyboard stroke

/*****************************************************************************
 * Global variables for the module
 *****************************************************************************/

/*****************************************************************************
 * Applicative messages definitions
 *****************************************************************************/
 #define LED_MSG_OFF			63
 #define LED_MSG_ON				64
 #define MRX_TSK_POL			65
 #define MRX_TSK_BLCD			66
 #define KBD_EVENT				67

 /*****************************************************************************
 * TTY RX task
 *****************************************************************************/
VOID APPmrx_task(YASK_MSG_T *my_mbx)
{
static BOOL lcd_blink = FALSE;
static LT08 lt08_lcd;
static char tmr;

	if( my_mbx)
		{
		switch(my_mbx->idn)
			{
			case MRX_TSK_POL :
					LT08print_text(&lt08_lcd, 1, 1, "%c", (WORD) my_mbx->eid);
				break;
			case MRX_TSK_BLCD :
				if(!lcd_blink)
					{
					lcd_blink = TRUE;
					LT08print_text(&lt08_lcd, 2, 5, "       ");
					}
				else
					{
					lcd_blink = FALSE;
					LT08print_text(&lt08_lcd, 2, 5, (ROMS *)"WELCOME");
					}
				break;
			}
		}
	else
		{
		// Register a timer
		tmr = YASKtmr_register( APPmrx_task, (roms *) "MrxTmr", 1000);
		
		// Start the timer
		YASKtmr_start( tmr, 0, MRX_TSK_BLCD, YASK_PRI_TSK);
		
		// Initialize LCD
		LT08open(&lt08_lcd, 2, 16, 0x40, 
						LCD_RS, LCD_RW, LCD_E, LCD_BL, 
						LCD_D7, LCD_D6, LCD_D5, LCD_D4);
						
		// Activate backlight
		LT08backlight(&lt08_lcd, TRUE);
		
		// Welcome message
		LT08print_text(&lt08_lcd, 2, 5, (ROM CHAR*)"WELCOME");
		
		}
}
 
/*****************************************************************************
 * LED applicative task
 *****************************************************************************/
VOID APPled_task( YASK_MSG_T *my_mbx) 
{
static char tmr;
 
	// After the first call, we need to manage the incoming mails
	if( my_mbx)
	{
		//TTYprintf( 0, (const rom char *) "APPled_task new mail %d\r\n", (WORD) my_mbx->idn);	
		switch( my_mbx->idn)
		{
				case LED_MSG_OFF:
					APM_LED_OFF;
					YASKtmr_start( tmr, 1000, LED_MSG_ON, YASK_PRI_TSK);
				break;
				
				case LED_MSG_ON:
					APM_LED_ON;
					YASKtmr_start( tmr, 10, LED_MSG_OFF, YASK_PRI_TSK);
				break;
				
				default:
				break;		
		}
	}
	else // First call with NULL pointer : initialization
	{
		// Register a timer
		tmr = YASKtmr_register( APPled_task, (roms *) "LedTmr", 0);
		
		// Start the timer with an ON status
		YASKtmr_start( tmr, 100, LED_MSG_ON, YASK_PRI_TSK);
	}

} // End of APPled_task()

/*****************************************************************************
 * User service : posts a mail to the buz task on each keyboard stroke
 * The UART device has been opened by the board initialization routine 
 *****************************************************************************/
VOID APPkbd_serv( YASK_MSG_T *my_mbx) 
{ 
CHAR c;
static char client_hdl, tmr;

	 // After the first call, we need to manage the keyboard events
	 // This service executes as fast as possible
	 
	if( my_mbx)
	{
		switch(my_mbx->idn)
		{
			case KBD_EVENT :
				while( TTYnready( 0))
				{
					// Read the received character and put the last in the mail
					c = TTYgetc( 0);
					
					// On poste le message
					YASKmsg_post( client_hdl, MRX_TSK_POL, (ulong) c, YASK_PRI_TSK);
				}
				break;
			default :
				break;
			
		}
	}
	else // First call with NULL pointer : initialization
	{
		// I register an auto reload polling timer
		tmr = YASKtmr_register( APPkbd_serv, (roms *) "KbdTmr", 10);
		
		// Start the timer 
		YASKtmr_start( tmr, 0, KBD_EVENT, YASK_PRI_TSK);
		
		// Register a mailbox to send the keystroke  to the client task		
		client_hdl = YASKmbx_register( APPmrx_task, (roms *) "MrxKey");
		
		TTYprintf( 0, (const rom char *) "Init APPkbd_serv\r\n");
	}
} // End of APPkbd_serv()


/*****************************************************************************
 * User program entry - called once by the kernel
 *****************************************************************************/
VOID APPmain(VOID)
{
	// (System initialization is performed by the kernel)

	// HW initialization
	apm_hal_init();

	// Open RS232 communication
	TTYopen( 	0,
				TTY_ASYNCH_MODE &
				TTY_EIGHT_BIT &
				TTY_CONT_RX &
				TTY_BRGH_HIGH,
				(DWORD) 9600);

	// Print message for service registration
	TTYprintf( 0, (const rom char *) "YASK_test_APM : in app_main registering user services to YASK...\r\n");

	// It is a good practice to register the services first and the tasks afterwards
	// So, the services will be stored at the beginning of the mailbox table and thus be called quicker during secheduling.

	// Keyboard service
	APPkbd_serv( NULL);

	// Print message
	TTYprintf( 0, (const rom char *) "YASK_test_APM : in app_main registering tasks to YASK...\r\n");

	// Initialize and register the several tasks
	APPled_task( NULL);
	APPmrx_task(NULL);

	// Print message
	TTYprintf( 0, (const rom char *) "YASK_test_APM : in app_main - Let's Go....\r\n");

	//YASKmon_open( 0, 0, 0);
	//YASKmon_init( YASK_MON_ALL);	
	// Let's go !
} // End of app_main()

/*****************************************************************************
 * Hardware abstraction layer initialization
 *****************************************************************************/
VOID apm_hal_init(VOID)
{
	//disable WDT
	WDTCONbits.SWDTEN = 0;

	// Port A is digital
	ADCON1 = 0x0F;

	// Pull ups on port B
	INTCON2 = 0x00;

	INTCON3 = 0x00;

	// Open and configure ADC
	//ADCinit( ADC_CFG_DDDDDDDDDDA , ADC_TAD_16, ADC_DIV_16);
	ADCON1 = 0x0F;

	// RA0 - Voltage measurement analog input
	TRISAbits.TRISA0 = IN;

	// RA1 - Function PB input
	//TRISAbits.TRISA1 = IN;

	// RA2 - Run LED - 1 to light
	PORTAbits.RA2 = 0;
	TRISAbits.TRISA2 = OUT;

	// RA3 => 1 Wire
	PORTAbits.RA3 = 1;
	TRISAbits.TRISA3 = IN;

	// RA4 to RA5 - Not used ==> outputs
	TRISAbits.TRISA4 = OUT;
	TRISAbits.TRISA5 = OUT;

	// RA6 - RA7 : Crystal oscillator - no initialization

	// RB0 - RF interrupt - configure as input
	TRISBbits.TRISB0 = IN;

	// RB1 - I2C interrupt - configure as input
	TRISBbits.TRISB1 = IN;

	// RB2 - NC ==> output
	TRISBbits.TRISB2 = OUT;

	// RB3 - I2C SCL - configure as input
	TRISBbits.TRISB3 = IN;

	// RB4 - I2C SDA - configure as input
	TRISBbits.TRISB4 = IN;

	// RB5 - RF reset - configure as output
	PORTBbits.RB5 = 1;
	TRISBbits.TRISB5 = OUT;

	// RB6 - PGC
	// RB7 - PGD

	// RC0 - ADC CS - output
	PORTCbits.RC0 = 1;
	TRISCbits.TRISC0 = OUT;

	// RC1 - RF CS - output
	PORTCbits.RC1 = 1;
	TRISCbits.TRISC1 = OUT;

	// RC2 - RF WAKE - output
	PORTCbits.RC2 = 1;
	TRISCbits.TRISC2 = OUT;

	// RC3 - SPI SCK - has to be set as an output
	PORTCbits.RC3 = 0;
	TRISCbits.TRISC3 = OUT;

	// RC4 - Used as SPI SDI has to be set as an input
	PORTCbits.RC4 = 1;
	TRISCbits.TRISC4 = IN;

	// RC5 -  SPI SDO connected - Set as digital output
	PORTCbits.RC5 = 0;
	TRISCbits.TRISC5 = OUT;

	// RC6 - EUSART TXD
	// RC7 - EUSART RXD

	// Setup SPI
	SSPSTAT = 0xC0;
	SSPCON1 = 0x20;  // 0x22 = clock / 64 - 0x21 = Clock/16 - 0x20 = Clock / 4;

} // End of apm_hal_init()


//---------------------------- End of file ------------------------------------------
